jetcrab\vm\executor/
traits.rs

1//! # VM Execution Traits
2//!
3//! Defines the core traits that provide the interface for VM execution components.
4//! These traits define the contract that implementations must fulfill for stack
5//! operations, heap management, variable management, and instruction execution.
6//!
7//! ## Core Traits
8//!
9//! - **StackOperations**: Defines stack manipulation operations
10//! - **HeapOperations**: Defines heap memory management operations
11//! - **VariableManager**: Defines variable storage and retrieval operations
12//! - **InstructionExecutor**: Defines the main execution interface
13//!
14//! ## Design Principles
15//!
16//! The traits follow these design principles:
17//!
18//! - **Generic Implementation**: Use trait bounds for flexibility
19//! - **Clear Contracts**: Each trait has a well-defined responsibility
20//! - **Error Handling**: All operations return Result types
21//! - **Performance**: Optimized for common operations
22//!
23//! ## Usage
24//!
25//! ```rust
26//! use jetcrab::vm::executor::traits::{StackOperations, HeapOperations, VariableManager};
27//!
28//! struct MyVM<S, H, V>
29//! where
30//!     S: StackOperations,
31//!     H: HeapOperations,
32//!     V: VariableManager,
33//! {
34//!     stack: S,
35//!     heap: H,
36//!     variables: V,
37//! }
38//! ```
39
40use crate::vm::bytecode::Bytecode;
41use crate::vm::handle::HeapHandleId;
42use crate::vm::types::{ArgIndex, ArraySize, LocalIndex};
43use crate::vm::value::Value;
44
45/// Defines operations for manipulating the VM's operand stack
46///
47/// This trait provides the interface for all stack operations including
48/// pushing, popping, and inspecting stack contents.
49pub trait StackOperations {
50    /// Pushes a value onto the top of the stack
51    ///
52    /// # Arguments
53    /// * `value` - The value to push onto the stack
54    fn push(&mut self, value: Value);
55
56    /// Pops a value from the top of the stack
57    ///
58    /// # Returns
59    /// * `Some(value)` if the stack is not empty
60    /// * `None` if the stack is empty
61    fn pop(&mut self) -> Option<Value>;
62
63    /// Peeks at the top value without removing it
64    ///
65    /// # Returns
66    /// * `Some(&value)` if the stack is not empty
67    /// * `None` if the stack is empty
68    fn peek(&self) -> Option<&Value>;
69
70    /// Clears all values from the stack
71    fn clear(&mut self);
72
73    /// Gets the current number of values on the stack
74    ///
75    /// # Returns
76    /// * The number of values currently on the stack
77    fn len(&self) -> usize;
78
79    /// Checks if the stack is empty
80    ///
81    /// # Returns
82    /// * `true` if the stack contains no values
83    /// * `false` if the stack contains at least one value
84    fn is_empty(&self) -> bool;
85
86    /// Gets a mutable reference to the underlying stack
87    ///
88    /// This allows direct access to the stack for advanced operations
89    /// that cannot be expressed through the trait interface.
90    ///
91    /// # Returns
92    /// * A mutable reference to the underlying stack
93    fn stack_mut(&mut self) -> &mut crate::vm::stack::Stack;
94
95    /// Gets the current size of the stack
96    ///
97    /// This is a convenience method that delegates to `len()`.
98    ///
99    /// # Returns
100    /// * The number of values currently on the stack
101    fn size(&self) -> usize {
102        self.len()
103    }
104}
105
106/// Defines operations for managing the VM's heap memory
107///
108/// This trait provides the interface for all heap operations including
109/// object allocation, property access, and memory management.
110pub trait HeapOperations {
111    /// Allocates a new object on the heap
112    ///
113    /// # Returns
114    /// * A handle to the newly allocated object
115    fn alloc_object(&mut self) -> HeapHandleId;
116
117    /// Allocates a new array on the heap
118    ///
119    /// # Returns
120    /// * A handle to the newly allocated array
121    fn alloc_array(&mut self) -> HeapHandleId;
122
123    /// Allocates a new function on the heap
124    ///
125    /// # Arguments
126    /// * `bytecode` - The function's bytecode
127    /// * `arg_count` - The number of arguments the function accepts
128    /// * `local_count` - The number of local variables the function uses
129    ///
130    /// # Returns
131    /// * A handle to the newly allocated function
132    fn alloc_function(
133        &mut self,
134        bytecode: Bytecode,
135        arg_count: ArgIndex,
136        local_count: LocalIndex,
137    ) -> HeapHandleId;
138
139    /// Gets a property value from an object
140    ///
141    /// # Arguments
142    /// * `handle` - The handle to the object
143    /// * `key` - The name of the property to retrieve
144    ///
145    /// # Returns
146    /// * `Some(&value)` if the property exists
147    /// * `None` if the property does not exist
148    fn get_object_property(&self, handle: HeapHandleId, key: &str) -> Option<&Value>;
149
150    /// Sets a property value on an object
151    ///
152    /// # Arguments
153    /// * `handle` - The handle to the object
154    /// * `key` - The name of the property to set
155    /// * `value` - The value to assign to the property
156    fn set_object_property(&mut self, handle: HeapHandleId, key: String, value: Value);
157
158    /// Sets an element in an array
159    ///
160    /// # Arguments
161    /// * `handle` - The handle to the array
162    /// * `index` - The index where to set the element
163    /// * `value` - The value to assign to the array element
164    fn set_array_element(&mut self, handle: HeapHandleId, index: ArraySize, value: Value);
165
166    /// Gets a reference to the underlying heap
167    ///
168    /// This allows direct access to the heap for advanced operations
169    /// that cannot be expressed through the trait interface.
170    ///
171    /// # Returns
172    /// * A reference to the underlying heap
173    fn get_heap(&self) -> &crate::vm::heap::Heap;
174
175    /// Gets an element from an array
176    ///
177    /// # Arguments
178    /// * `handle` - The handle to the array
179    /// * `index` - The index of the element to retrieve
180    ///
181    /// # Returns
182    /// * `Some(&value)` if the element exists at the given index
183    /// * `None` if the index is out of bounds
184    fn get_array_element(&self, _handle: HeapHandleId, _index: ArraySize) -> Option<&Value> {
185        None
186    }
187
188    /// Checks if an object has a specific property
189    ///
190    /// # Arguments
191    /// * `handle` - The handle to the object
192    /// * `key` - The name of the property to check
193    ///
194    /// # Returns
195    /// * `true` if the property exists
196    /// * `false` if the property does not exist
197    fn has_object_property(&self, handle: HeapHandleId, key: &str) -> bool {
198        self.get_object_property(handle, key).is_some()
199    }
200
201    /// Gets the length of an array
202    ///
203    /// # Arguments
204    /// * `handle` - The handle to the array
205    ///
206    /// # Returns
207    /// * The number of elements in the array
208    fn get_array_length(&self, _handle: HeapHandleId) -> usize {
209        0
210    }
211}
212
213/// Defines operations for managing VM variables
214///
215/// This trait provides the interface for all variable operations including
216/// local variables, global variables, and function arguments.
217pub trait VariableManager {
218    /// Gets a local variable by index
219    ///
220    /// # Arguments
221    /// * `idx` - The index of the local variable
222    ///
223    /// # Returns
224    /// * `Some(&value)` if the variable exists
225    /// * `None` if the variable does not exist
226    fn get_local(&self, idx: usize) -> Option<&Value>;
227
228    /// Sets a local variable by index
229    ///
230    /// # Arguments
231    /// * `idx` - The index of the local variable
232    /// * `value` - The value to assign to the variable
233    fn set_local(&mut self, idx: usize, value: Value);
234
235    /// Gets a global variable by index
236    ///
237    /// # Arguments
238    /// * `idx` - The index of the global variable
239    ///
240    /// # Returns
241    /// * `Some(&value)` if the variable exists
242    /// * `None` if the variable does not exist
243    fn get_global(&self, idx: usize) -> Option<&Value>;
244
245    /// Sets a global variable by index
246    ///
247    /// # Arguments
248    /// * `idx` - The index of the global variable
249    /// * `value` - The value to assign to the variable
250    fn set_global(&mut self, idx: usize, value: Value);
251
252    /// Gets a mutable reference to a local variable by index
253    ///
254    /// # Arguments
255    /// * `idx` - The index of the local variable
256    ///
257    /// # Returns
258    /// * `Some(&mut value)` if the variable exists
259    /// * `None` if the variable does not exist
260    fn get_local_mut(&mut self, idx: usize) -> Option<&mut Value>;
261
262    /// Gets a mutable reference to a global variable by index
263    ///
264    /// # Arguments
265    /// * `idx` - The index of the global variable
266    ///
267    /// # Returns
268    /// * `Some(&mut value)` if the variable exists
269    /// * `None` if the variable does not exist
270    fn get_global_mut(&mut self, idx: usize) -> Option<&mut Value>;
271
272    /// Gets a function argument by index
273    ///
274    /// This is a convenience method that delegates to `get_local()`.
275    ///
276    /// # Arguments
277    /// * `idx` - The index of the argument
278    ///
279    /// # Returns
280    /// * `Some(&value)` if the argument exists
281    /// * `None` if the argument does not exist
282    fn get_argument(&self, idx: usize) -> Option<&Value> {
283        self.get_local(idx)
284    }
285
286    /// Sets a function argument by index
287    ///
288    /// This is a convenience method that delegates to `set_local()`.
289    ///
290    /// # Arguments
291    /// * `idx` - The index of the argument
292    /// * `value` - The value to assign to the argument
293    fn set_argument(&mut self, idx: usize, value: Value) {
294        self.set_local(idx, value);
295    }
296}
297
298/// Defines the main interface for VM instruction execution
299///
300/// This trait provides the core execution interface that the VM uses
301/// to run bytecode programs.
302pub trait InstructionExecutor {
303    /// Executes a bytecode program
304    ///
305    /// # Arguments
306    /// * `bytecode` - The bytecode to execute
307    /// * `constants` - The constant pool for the bytecode
308    ///
309    /// # Returns
310    /// * `Ok(())` on successful execution
311    /// * `Err(ExecutionError)` if execution fails
312    fn execute(
313        &mut self,
314        bytecode: &Bytecode,
315        constants: &[Value],
316    ) -> Result<(), crate::vm::executor::error_handler::ExecutionError>;
317}